import Mixin from './mixin'
import Listener from './listener'
import Emitter from './emitter'
import Logger from './logger'
import SocketIo from 'socket.io-client'
import Config from './config'
import axios from 'axios'
import AgoraRTCClient from './agoraClient'

export class LaunchVueImSocket {
    /**
     * @param vuex
     * @param debug
     * @param options
     * @param options.isOversea
     * @param options.isDev
     */
    constructor({
        vuex,
        debug,
        options
    }) {
        Logger.debug = debug;
        this.options = options
        this.io = this.connect(options)
        this.agoraClient = null
        this.emitter = new Emitter(vuex)
        this.listener = new Listener(this.io, this.emitter)
        this.getHistory = this.getHistoryFunc(options)
    }

    install(Vue) {
        const version = Number(Vue.version.split('.')[0])

        if (version >= 3) {
            Vue.config.globalProperties.$socket = this.io
            Vue.config.globalProperties.$imSocketIo = this
        } else {
            Vue.prototype.$socket = this.io
            Vue.prototype.$imSocketIo = this
        }

        Vue.mixin(Mixin)

        Logger.info('launch-vue-im-socket.io plugin installed')
    }

    /**
     * @param options 
     * @returns 
     */
    connect(options) {
        let port = Config.APP_WEBSOCKET_PORT
        if (location.protocol.indexOf('https') > -1) {
            port = Config.APP_PORT_HTTPS
        }

        let hostname = 'remote.x431.com'
        if (options.isOversea) {
            hostname = 'remotediag.x431.com'
        }
        if (options.isDev) {
            hostname = 'remote.test.x431.com'
            port = 80
        }
        const url = `${location.protocol}//${hostname}:${port}`


        let socket = SocketIo(url)
        return socket
    }

    /**
     * @param {*} caller_user_id 
     * @param {*} target_user_id 
     * @param {*} current_user_id
     * @returns channel and token
     * @then 发送邀请message
     */
    getRtcToken(caller_user_id, target_user_id, current_user_id) {
        let roomCode = caller_user_id.toString() + target_user_id.toString()
        return new Promise((resolve, reject) => {
            AgoraRTCClient.getRtcToken(current_user_id, roomCode, this.options).then(res => {
                if (res.code == 0) {
                    resolve({
                        channel: roomCode,
                        token: res.data
                    })
                } else {
                    reject(res.msg)
                }
            }).catch(err => {
                reject(err)
            })
        })
    }

    resetAgora() {
        this.agoraClient.leave()
        this.agoraClient.reset()
    }

    async startCall(caller_user_id, target_user_id, current_user_id, mediaType) {
        const client = new AgoraRTCClient(this.emitter, this.options)
        if (!client._created) {
            await client.createClient({ mode: 'rtc', codec: 'vp8' })
            client._created = true
        }
        this.agoraClient = client
        this.rtcClientListner(this.agoraClient)
        this.agoraClient.clientListener()
        this.joinEvent(this.agoraClient, caller_user_id, target_user_id, current_user_id, mediaType).then(client => {
            console.log(client)
        })
    }

    joinEvent(client, caller_user_id, target_user_id, current_user_id, mediaType) {
        let roomCode = caller_user_id.toString() + target_user_id.toString()
        return new Promise((resolve, reject) => {
            AgoraRTCClient.getRtcToken(current_user_id, roomCode, this.options).then(res => {
                let config = {
                    channel: roomCode,
                    token: res.data
                }
                if (roomCode && client._created && client._joined === false) {
                    let options = {
                        uid: current_user_id,
                        mediaType: mediaType,
                        ...config
                    }
                    client.join(options).then(() => {
                        resolve(client)
                    }).catch(err => {
                        client.leave()
                        reject(err)
                    })
                }
            })
        })
    }

    rtcClientListner(client) {
        client.on("connection-state-change", (curState) => {
            console.log('connection-state-change: ', curState)
        })

        client.on('user-joined', (user) => {
            console.log('user-joined: ', user)
        })

        //远端用户取消发布了音频或视频轨道。
        client.on("user-unpublished", (user, mediaType) => {
            if (mediaType == "video") {
                client.controlStream("video", false)
            }
        });

        //远端用户离开频道。
        client.on("user-left", (user, reason) => {
            this.agoraClient && this.agoraClient.leave()
        })
    }

    getHistoryFunc(options) {
        let port = Config.APP_WEBSOCKET_PORT
        if (location.protocol.indexOf('https') > -1) {
            port = Config.APP_PORT_HTTPS
        }

        let hostname = 'remote.x431.com'
        if (options.isOversea) {
            hostname = 'remotediag.x431.com'
        }
        if (options.isDev) {
            hostname = 'remote.test.x431.com'
            port = 80
        }

        return ({ userId, targetId, page, isSupport }) => {
            page = page > 0 ? page - 1 : 0
            return new Promise((resolve, reject) => {
                try {
                    axios({
                        baseURL: `${location.protocol}//${hostname}`,
                        url: `/getClientHistory?senderId=${userId}&receiverId=${targetId}&currentPage=${page}&pageSize=30` + (isSupport ? '&isCustomer=2' : ''),
                        method: 'get'
                    }).then(res => {
                        resolve(res.data)
                    }).catch(err => {
                        reject(err)
                    })
                } catch (error) {
                    reject(error)
                }
            })
        }
    }
}

export default LaunchVueImSocket